﻿using System;
using System.Xml;
using System.Windows.Forms;
using SdmxMl.Common;


namespace SdmxMl.Structure
{
    public interface IFlowRef
    {
        ArtefactRefTyped ReferencedArtefact { get; }
    }

    /// <summary>
    /// DataflowType describes the structure of a data flow.
    /// A human-readable name must be provided, and may be given in
    /// several language-specific variations. A longer human-readable
    /// description (also in multiple language-specific versions) may
    /// be provided. A reference must be made to a key family, and to
    /// a category within a category scheme, using the KeyFamilyRef
    /// and CategoryRef elements, unless the Dataflow is a reference
    /// to an external data flow, in which case a url must be provided
    /// in the uri attribute, and the isExternalReference attribute must
    /// be set to true.. Annotations may be provided in the Annotations
    /// element. An id unique to the maintaining agency (identified in
    /// the agencyID attribute) must be supplied in the "id" attribute;
    /// a version may be specified, and is assumed to be "1.0" if not
    /// supplied. The urn attribute may contain a valid registry URN
    /// (as per the SDMX Registry Specification). If the dataflow is final,
    /// the isFinal attribute must have a value of true - any production
    /// dataflow must be final (that is, it cannot be changed without
    /// versioning). The validFrom and validTo attributes provide inclusive
    /// dates for providing supplemental validity information about the version.
    /// </summary>
    public class DataflowType : Artefact, IFlowRef
    {
        #region Properties

        public override ArtefactRefTypedList ArtefactRefList
        {
            get
            {
                ArtefactRefTypedList list = new ArtefactRefTypedList();
                if (KeyFamilyRef.IsFilled)
                {
                    ArtefactRefTyped at = new ArtefactRefTyped(
                       SdmxMl.Manager.SdmxArtefactType.KeyFamilies,
                       KeyFamilyRef.Id, KeyFamilyRef.AgencyId, KeyFamilyRef.Version);
                    if (list.Contains(at.Type, at.FullIdent) == false)
                        list.Add(at);
                }

                return list;
            }
        }


        private DataFlowInsider _dataFlowInsider;
        public KeyFamilyRefType KeyFamilyRef
        {
            get { return _dataFlowInsider.DSDRef; }
        }

        #endregion //Properties

        #region Constructors

        public DataflowType()
            : base()
        {
            _dataFlowInsider = new DataFlowInsider();
        }


        public DataflowType(XmlNode nodeArtefact, SdmxNamespaceManager nsmgr) 
            : base(nodeArtefact, nsmgr)
        {
            _dataFlowInsider = new DataFlowInsider(nodeArtefact, nsmgr);
        }

        #endregion //Constructors

        #region Tree

        public override TreeNode FillNode(TreeNode parentNode)
        {
            TreeNode t = base.FillNode(parentNode);
            TreeNode td = new TreeNode(_dataFlowInsider.ToString(), 0, 0);
            t.Nodes.Add(td);
            td.Tag = _dataFlowInsider;

            return t;
        }

        #endregion // Tree

        #region XML serialize

        public override void WriteXmlInsider(XmlTextWriter xw)
        {
            _dataFlowInsider.WriteXmlInsider(xw);
        }

        #endregion

        #region IFlowRef Members

        public ArtefactRefTyped ReferencedArtefact
        {
            get 
            {
                return new ArtefactRefTyped(SdmxMl.Manager.SdmxArtefactType.KeyFamilies,
                    KeyFamilyRef.FullIdent);
            }
        }

        #endregion

        #region Artefact Type

        public override Manager.SdmxArtefactType ArType
        {
            get { return Manager.SdmxArtefactType.Dataflows; }
        }

        #endregion

    }

    // Intermediate Class constructed to help Edition
    public class DataFlowInsider
    {
        #region Properties

        private KeyFamilyRefType _keyFamilyRef;
        public KeyFamilyRefType DSDRef
        {
            get { return _keyFamilyRef; }
        }

        #endregion //Properties

        #region Constructors

        public DataFlowInsider()
        {
            Init();
        }

        private void Init()
        {
            _keyFamilyRef = new KeyFamilyRefType();
        }

        public DataFlowInsider(XmlNode nodeArtefact, SdmxNamespaceManager nsmgr) 
        {
            Init();

            string query = nsmgr.VersionSdmx == SdmxVersion.SDMX_20 ?
                "./structure:KeyFamilyRef" : "./structure:Structure";

            // DSD Ref ?
            XmlNode nodeDsd = nodeArtefact.SelectSingleNode(query, nsmgr);
            if (nodeDsd != null)
                _keyFamilyRef = new KeyFamilyRefType(nodeDsd, nsmgr);
        }

        #endregion //Constructors

        #region XML serialize

        public void WriteXmlInsider(XmlTextWriter xw)
        {
            string prefix = "structure";
            _keyFamilyRef.WriteXml(xw, prefix, "KeyFamilyRef");

        }

        #endregion


        public override string ToString()
        {
            return _keyFamilyRef.ToString();
        }
    }
}
